#include "labelscene.h"
#include "vertexitem.h"
#include <polygonitem.h>
#include <QGraphicsScene>
#include <QMainWindow>
#include <QGraphicsSceneEvent>
#include <QGraphicsItem>
#include <QApplication>
#include <QList>

LabelScene::LabelScene(QObject* parent)
    :  QGraphicsScene(parent)
{


}

void LabelScene::setMode(Mode mode)
{
    myMode = mode;
    qDebug() << (cursorFollower == nullptr);
    if(myMode == CreatePolygon || myMode == CreateRectangle)
    {
        if(cursorFollower == nullptr)
        {
            cursorFollower = new VertexItem(QPointF(0, 0), VertexItem::Unplaced, this);
            addItem(cursorFollower);
            cursorFollower->setZValue(1000);
            cursorFollower->setPos(QPointF(-10000, -10000));
        }
    }
    else
    {
        if(cursorFollower != nullptr)
        {
            removeItem(cursorFollower);
        }

        cursorFollower = nullptr;
    }

}
void LabelScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
    // qDebug() << "myMode is:" << myMode;
    switch (myMode) {
    case CreatePolygon:
    case CreateRectangle:
        if(!sceneRect().contains(mouseEvent->scenePos())) return;
        if (mouseEvent->buttons() & Qt::LeftButton)
        {
            return;
        }

        cursorFollower->setPos(mouseEvent->scenePos());
        if(isDrawing())
        {
            createShadowPolygon();
        }
        // break;


        break;
    case EditPolygon:

        if (mouseEvent->buttons() & Qt::LeftButton)
        {

            if(isItemChange(VertexItem::Type) && selectedItems().count() == 1)
            {

                VertexItem *vertex = qgraphicsitem_cast<VertexItem*>(selectedItems().first());
                QPolygonF polygon = vertex->polygonItem()->polygon();
                if(vertex->polygonItem()->getIsRectangle())
                {
                    int x = vertex->polygonItem()->pos().x();
                    int y = vertex->polygonItem()->pos().y();
                    if(vertex->index() == 1)
                    {
                        polygon[1] = QPointF(polygon[0].x() + x , vertex->pos().y()) - vertex->polygonItem()->pos();
                        polygon[2] = vertex->pos() - vertex->polygonItem()->pos();
                        polygon[3] = QPointF(vertex->pos().x(), polygon[0].y() + y) - vertex->polygonItem()->pos();
                    }else if(vertex->index() == 0)
                    {
                        polygon[0] = vertex->pos() - vertex->polygonItem()->pos();
                        polygon[1] = QPointF(vertex->pos().x(), polygon[2].y() + y) - vertex->polygonItem()->pos();
                        polygon[3] = QPointF(polygon[2].x() + x, vertex->pos().y()) - vertex->polygonItem()->pos();
                    }

                }else
                {
                    polygon[vertex->index()] = vertex->pos() - vertex->polygonItem()->pos();
                }

                vertex->polygonItem()->setPolygon(polygon);
            }
            // if(isItemChange(PolygonItem::Type))
            // {
            //     PolygonItem *polygonItem = nullptr;
            //     for(QGraphicsItem* item: selectedItems())
            //     {
            //         PolygonItem *target = qgraphicsitem_cast<PolygonItem*>(item);
            //         if(target != nullptr)
            //         {
            //             polygonItem = target;
            //         }
            //     }
            // }
        }
        QGraphicsScene::mouseMoveEvent(mouseEvent);
        break;


    }

}

void LabelScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
    QGraphicsScene::mouseReleaseEvent(mouseEvent);
}
void LabelScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
    qDebug() << "mousePressEvent";
    if(mouseEvent->button() == Qt::RightButton)
    {
        return;
    }


    // 正常单击处理
    if (mouseEvent->button() == Qt::LeftButton) {
        switch (myMode) {
        case CreatePolygon:
        case CreateRectangle:
            if(!sceneRect().contains(mouseEvent->scenePos())) return;
            if(!isDrawing())
            {
                // create the first vertex of polygon
                //initialize the polygon
                currentPolygonItem = new PolygonItem(this);
                addItem(currentPolygonItem);
                addVertexToPolygon(new VertexItem(mouseEvent->scenePos(), VertexItem::Placed, this));
            }else
            {
                if(isVertexOverlap(mouseEvent->scenePos())) return;
                // create the second, third, ... vertex(but not the last vertex) of the polygon
                addVertexToPolygon(new VertexItem(mouseEvent->scenePos(), VertexItem::Placed, this));
            }
            // break;

            break;
        case EditPolygon:

            clearSelection();
            QGraphicsScene::mousePressEvent(mouseEvent);
            if(isItemChange(PolygonItem::Type))
            {
                PolygonItem *item = qgraphicsitem_cast<PolygonItem*>(selectedItems().first());
                for(VertexItem *vertex: item->vertexes())
                {
                    vertex->setSelected(true);

                }
            }


            break;
        }
    }


}
void LabelScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
    qDebug() << "mouseDoubleClickEvent";
    if (mouseEvent->button() == Qt::LeftButton) {
        switch (myMode) {
        case CreatePolygon:
        case CreateRectangle:
            if(!sceneRect().contains(mouseEvent->scenePos())) return;
            if(isDrawing())
            {
                if(myMode == CreateRectangle)
                {
                    if(count == 1)
                    {
                        VertexItem* vertexItem = new VertexItem(mouseEvent->scenePos(), VertexItem::Placed, this);
                        vertexItem->setIndex(count);
                        addItem(vertexItem);
                        currentPolygonItem->appendVertexToRectangle(vertexItem);
                        vertexItem->setPolygonItem(currentPolygonItem);
                        currentPolygonItem->setRectangle();
                    }
                }
                count = 0;
                currentPolygonItem->setPolygon(currentPolygonItem->polygon());
                PolygonItem *polygonItem = currentPolygonItem;
                // qDebug() << "the created polygon is" << polygonItem;
                // qDebug() << "vertex is" << polygonItem->vertexes();
                qDebug() << currentPolygonItem->polygon();
                currentPolygonItem = nullptr;
                isMoving = true;

                //send add polygon signal to MainWindow


                // LabelDialog *dialog = new LabelDialog;
                // if (dialog->exec() == QDialog::Accepted) {
                //     QString labelName = dialog->labelName();
                //
                //     qDebug() << "User entered label name:" << labelName;
                // }
                emit polygonCreated(polygonItem);

            }
            break;


        case EditPolygon:

            break;
        }

    }
    QGraphicsScene::mouseDoubleClickEvent(mouseEvent);
}

bool LabelScene::isVertexOverlap(QPointF point)
{
    qDebug() << "isoverlaptest";
    QList<QGraphicsItem *> items = this->items(point);
    for(QGraphicsItem * item: items)
    {
        VertexItem * vertex = qgraphicsitem_cast<VertexItem *>(item);
        if(vertex != nullptr && vertex->state() == VertexItem::Placed)
        {
            qDebug() << "overlap vertex";
            return true;
        }
    }
    return false;
}

void LabelScene::createShadowPolygon()
{
    switch (myMode) {
    case CreatePolygon:
        if (!isMoving)
        {
            //start shadow polygon
            currentPolygonItem->addVertex(cursorFollower, isMoving, !isMoving);
            isMoving = true;
        } else
        {
            //continue shadow polygon
            currentPolygonItem->addVertex(cursorFollower, isMoving, isMoving);
        }
        break;
    case CreateRectangle:
        if (!isMoving)
        {
            //start shadow polygon
            // new VertexItem(QPointF(0, 0), VertexItem::Unplaced, this);
            QPointF shallowPos1 = currentPolygonItem->vertexes()[0]->scenePos();
            QPointF shallowPos2 = cursorFollower->scenePos();
            // qDebug() << "shallow" << shallowPos1;
            // qDebug() << "shallow" << shallowPos2;
            currentPolygonItem->addVertex(new VertexItem(QPointF(shallowPos1.x(), shallowPos2.y()), VertexItem::Unplaced, this), isMoving, !isMoving);

            currentPolygonItem->addVertex(cursorFollower, isMoving, !isMoving);
            currentPolygonItem->addVertex(new VertexItem(QPointF(shallowPos2.x(), shallowPos1.y()), VertexItem::Unplaced, this), isMoving, !isMoving);
            isMoving = true;
        } else
        {
            QPointF shallowPos1 = currentPolygonItem->vertexes()[0]->scenePos();
            QPointF shallowPos2 = cursorFollower->scenePos();
            qDebug() << "shallow1" << shallowPos1 << "shallow2" << shallowPos2;
            //continue shadow polygon
            currentPolygonItem->addRectangle(cursorFollower, QPointF(shallowPos1.x(), shallowPos2.y()), QPointF(shallowPos2.x(), shallowPos1.y()));
        }
    default:
        break;
    }

}

void LabelScene::addVertexToPolygon(VertexItem *vertex)
{
    switch (myMode) {
    case CreatePolygon:
        vertex->setIndex(count);
        // qDebug() << "the index count is" << vertex->index() << "vertex is" << vertex;
        count++;
        addItem(vertex);
        currentPolygonItem->addVertex(vertex, isMoving, !isMoving);
        isMoving = false;
        break;
    case CreateRectangle:
        if(count == 0)
        {
            vertex->setIndex(count);
            count++;
            addItem(vertex);
            currentPolygonItem->addVertex(vertex, isMoving, !isMoving);
            isMoving = false;
        }else {
            return;
        }
    default:
        break;
    }

}

bool LabelScene::isItemChange(int type) const
{
    const QList<QGraphicsItem *> items = selectedItems();
    const auto cb = [type](const QGraphicsItem *item) { return item->type() == type; };
    return std::find_if(items.begin(), items.end(), cb) != items.end();
}
